﻿/****************************** Module Header ******************************\
 * Module Name:  EncryptHelper.cs
 * Module Version:  1.0.0 (2011-12-5)
 * Copyright (c) AnyEB.Com (14507247@qq.com)
 * 
 * This class is used to encrypt string or encrypt number.
 * 
 * This source is subject to the GPL License.
 * See http://www.gnu.org/licenses/gpl.html.
 * All other rights reserved.
 * 
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
 * EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
 * WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Web.Security;
using System.Security.Cryptography;
using System.IO;

namespace UCF.Core
{
    /// <summary>
    /// 加密/解密助手类
    /// <para>提供加密和解密的方法</para>
    /// </summary>
    public class EncryptHelper
    {
        //默认密钥向量
        private static byte[] Keys = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF };

        #region 系统自带的加密解密功能
        /// <summary>
        /// MD5加密字符串
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string MD5(string text)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(text, "MD5");
        }

        /// <summary>
        /// MD5加密字符串
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string MD5(string text,string key)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(text+key, "MD5");
        }

        /// <summary>
        /// 返回截短后的md5加密字符串
        /// </summary>
        /// <param name="text"></param>
        /// <param name="length"></param>
        /// <returns></returns>
        public static string MD5Lite(string text, int length = 6,string mixstr="md5lite")
        {
            string md5str = MD5(text);
            md5str = MD5(md5str + mixstr);
            if (length >= md5str.Length) return md5str;
            int len = length / 2;
            return md5str.Substring(0, len) + md5str.Substring(md5str.Length - len);
        }

        /// <summary>
        /// SHA1加密字符串
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string SHA1(string text)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(text, "SHA1");
        }
        #endregion

        #region SOMDA加密解密

        /// <summary>
        /// 加密版本号,生成两位版本代码
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        private static string Ever(int n)
        {
            string strDict = "abcdefghijklmnopqrstuvwxyz0123456789";
            Random rnd = new Random();
            int iRndNumber = rnd.Next(0, 27);
            return strDict[n + iRndNumber].ToString() + strDict[iRndNumber].ToString();
        }
        /// <summary>
        /// 解密版本号
        /// </summary>
        /// <param name="n"></param>
        /// <returns></returns>
        private static int Dever(string n)
        {
            string strDict = "abcdefghijklmnopqrstuvwxyz0123456789";
            int iRndNumber = strDict.IndexOf(n[1]);
            int iOut = strDict.IndexOf(n[0]) - iRndNumber;
            return iOut;
        }

        /// <summary>
        /// 获取SOMDA字典版本
        /// </summary>
        /// <param name="version"></param>
        /// <returns></returns>
        private static string[] GetSOMDADictionary(int version)
        {
            switch (version)
            {
                case 0:
                    return new string[] { "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "abcdefghijklmnopqrstuvwxyz", "0123456789" };
                case 1:
                    return new string[] { "fghiHIJKLMN567jkcdepwOPWXYZ01234xyzABCDqrQRSTUVstuvEFG89lmnoab", "fghijabcdpqxyzrstuvweklmno", "3456017892" };
                case 2:
                    return new string[] { "ghiHIJfK67jkcdLMN5eYZ01pwOPWX2zAB34xFG8yCDqrQRVstSTUuoabvE9lmn", "abcdpqxfgtuvweklmhisnojyzr", "5634092178" };
                case 3:
                    return new string[] { "7jgK6kcZ01pwOPWX2zAtSTUuovEnB34xFG8yCDqrQRa9lmdLMN5eYbVshiHIJf", "fghijklabcdestuvpqrzwxymno", "4056917823" };
                case 4:
                    return new string[] { "PWX2zcZ7jgK6k01pwOUuovEsh4xFG8yCDqAtSIJfnBTrQRa9lmdLMN5iH3eYbV", "ghiabcdefjkqrlmnvwxyopstuz", "6405823917" };
                case 5:
                    return new string[] { "cZ8yCgK6k01pwOUuPWX2MovEsh4xFGqAtSD7jIJfnB3eYbTrQN5iHVzRdLa9lm", "ijklabfghcdvpqrzwxymnoestu", "8640527391" };
                case 6:
                    return new string[] { "qAtSD7jIJfovEsh4xFGrnB3eYbT01pwOUuPWX2MQN5iHVzRdLa9lmcZ8yCgK6k", "bfghcijkmnoesladvxytupqrzw", "7456123890" };
                case 7:
                    return new string[] { "4xFGrnB3eYbT01qAtSD7jIJfN5iHVZ8yCgK6kzRovEshpwOUuPWX2MQdLa9lmc", "ijkmnoebfghcqrzwsytupladvx", "2305891764" };
                case 8:
                    return new string[] { "YbT01qAtSD5iHVZ8yCgK7jI4xFGrnB3eJfN6kzRUuPQdLa9lmcWovEshpwOX2M", "bfgijkmnoehcytuqrzwsdvxpla", "9301726458" };
                default:
                    return new string[] { "Z8yCtSD5iHVI9lmcWovEs4xFGrnqAdLahpwOX2MB3eJfN6kzRUuPQgK7jYbT01", "mnoehcbfgijkyrzwstuxplaqdv", "6415728930" };
            }
        }

        /// <summary>
        /// 加密字符串
        /// <para>支持英文,数字,符号加密,不支持汉字加密</para>
        /// <para>author:编程浪子; version:3.0.0 (2009-11-14)</para>
        /// <para>非常佩服俺自己，哈哈</para>
        /// <example>
        /// somda("_my2010password")=>ro4rp8zk7Kx4Gl5Zz1Tm4um5Ks2ql0wd8mt5wd4ks1Jx0
        /// somda("无法被加密")=>"无法被加密"
        /// </example>
        /// </summary>
        /// <param name="text"></param>
        /// <param name="maxLength"></param>
        /// <param name="version"></param>
        /// <returns></returns>
        public static string SOMDA(string text, int maxLength, int version)
        {
            if (text == null || text.Length == 0) return "";
            text = text.Length.ToString() + ":" + text;
            if (maxLength > 0) text = text.PadRight(maxLength / 3 - 1, '0');
            string strFixChar = "";
            string strAscChar = "";
            string strRemain = "";
            int intAscChar;
            int intMod;
            int intRnd;
            StringBuilder sb = new StringBuilder();
            string[] arrDict = GetSOMDADictionary(version);
            Random oRnd = new Random();
            foreach (char c in text)
            {
                intRnd = 256 + oRnd.Next(0, 62);
                strAscChar = ((byte)c + intRnd).ToString() + (318 - intRnd).ToString().PadLeft(2, '0');
                intAscChar = Int32.Parse(strAscChar);
                intMod = intAscChar / 252;
                strRemain = (intAscChar % 252).ToString().PadLeft(3, '0');
                strFixChar = arrDict[0][176 - intMod].ToString() + arrDict[1][Int32.Parse(strRemain.Substring(0, 2))].ToString() + arrDict[2][Int32.Parse(strRemain[2].ToString())].ToString();
                sb.Append(strFixChar);
            }
            return Ever(version) + sb.ToString();
        }

        /// <summary>
        /// 加密字符串
        /// </summary>
        /// <param name="text"></param>
        /// <param name="maxLength"></param>
        /// <returns></returns>
        public static string SOMDA(string text, int maxLength)
        {
            Random oRnd = new Random();
            return SOMDA(text, maxLength, oRnd.Next(0, 10));
        }
        /// <summary>
        /// 加密字符串，加密长度为原来的3倍
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static string SOMDA(string text)
        {
            return SOMDA(text, 0);
        }
        /// <summary>
        /// 解密由SoMDA加密的数据
        /// <para>author:编程浪子; version:2.0.1 (2009-11-14)</para>
        /// <para>狗日的，解密还真不简单。。。</para>
        /// <example>SODEMDA(SOMDA("my2020Pwd"))</example>
        /// <![CDATA[
        /// ==UPDATE====================================
        /// 2010-08-03 by 编程浪子,重写了解密算法，版本升级到2.0.0
        /// 2010-10-20 by sutroon,新增解密失败则返回原始值
        /// ]]>
        /// </summary>
        /// <param name="enctryText"></param>
        /// <returns></returns>
        public static string SODEMDA(string enctryText)
        {
            if (enctryText == null || enctryText.Length < 8) return "";
            if ((enctryText.Length - 2) % 3 > 0) return "";

            string[] arrDict = GetSOMDADictionary(Dever(enctryText.Substring(0, 2)));
            enctryText = enctryText.Substring(2);
            // 变量定义 
            StringBuilder sb = new StringBuilder();
            int intMod;
            int intRemain;
            int intAscChar;
            int intRnd;

            foreach (string s in enctryText.ToArray(3))
            {
                intMod = 176 - arrDict[0].IndexOf(s[0]);
                intRemain = Int32.Parse(arrDict[1].IndexOf(s[1]).ToString() + arrDict[2].IndexOf(s[2]).ToString());
                intAscChar = intMod * 252 + intRemain;
                intRnd = Int32.Parse(intAscChar.ToString().Substring(3, 2));
                intAscChar = Int32.Parse(intAscChar.ToString().Substring(0, 3));
                intRnd = 318 - intRnd;
                intAscChar = intAscChar - intRnd;
                sb.Append((char)intAscChar);
            }
            string sOut = sb.ToString();
            int intSplit = sOut.IndexOf(':');
            if (intSplit > -1)
            {
                int intLength = Int32.Parse(sOut.Substring(0, intSplit));
                sOut = sOut.Substring(intSplit + 1, intLength);
            }
            return sOut;
        }
        #endregion

        /// <summary>
        /// DES加密字符串[2012-7-30]
        /// </summary>
        /// <param name="encryptString">待加密的字符串</param>
        /// <param name="encryptKey">加密密钥,要求为8位</param>
        /// <returns>加密成功返回加密后的字符串，失败返回源串</returns>
        public static string EncryptByDES(string s, string key = "Aa#123#_")
        {
            byte[] rgbKey = Encoding.UTF8.GetBytes(key.Substring(0, 8));
            byte[] rgbIV = Keys;
            byte[] inputByteArray = Encoding.UTF8.GetBytes(s);
            DESCryptoServiceProvider dCSP = new DESCryptoServiceProvider();
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, dCSP.CreateEncryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Convert.ToBase64String(mStream.ToArray());
        }

        /// <summary>
        /// DES解密[2012-7-30]
        /// </summary>
        /// <param name="s"></param>
        /// <returns></returns>
        public static string DeEncryptByDES(string s, string key = "Aa#123#_")
        {
            byte[] rgbKey = Encoding.UTF8.GetBytes(key);
            byte[] rgbIV = Keys;
            byte[] inputByteArray = Convert.FromBase64String(s);
            DESCryptoServiceProvider DCSP = new DESCryptoServiceProvider();
            MemoryStream mStream = new MemoryStream();
            CryptoStream cStream = new CryptoStream(mStream, DCSP.CreateDecryptor(rgbKey, rgbIV), CryptoStreamMode.Write);
            cStream.Write(inputByteArray, 0, inputByteArray.Length);
            cStream.FlushFinalBlock();
            return Encoding.UTF8.GetString(mStream.ToArray());

        }
    }
}
